﻿using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Collections;
using umbraco.DataLayer;
using umbraco.BusinessLogic;
using umbraco.editorControls;
using System.Collections.Generic;
using System.Data.SqlClient;
using umbraco.NodeFactory;
using System.Web.SessionState;
using umbraco.BusinessLogic.Actions;
using umbraco.cms.businesslogic.web;
using umbraco.cms.businesslogic.property;
using umbraco.interfaces;
using ExtendedWorkFlow.Helpers;
using ExtendedWorkFlow.Commands;

namespace ExtendedWorkFlow.Watcher
{

    public class ExtendedWorkFlowActionWatcher : umbraco.BusinessLogic.Actions.IActionHandler
    {

        #region Properties

        /// <summary>
        /// Name of the watcher
        /// </summary>
        /// <returns></returns>
        String umbraco.BusinessLogic.Actions.IActionHandler.HandlerName()
        {
            // return the name of the custom action handler
            return "ExtendedWorkFlowHelper.ActionWatcher";
        }

        /// <summary>
        /// Action thate the watcheer is hooked into
        /// </summary>
        /// <returns></returns>
        umbraco.interfaces.IAction[] umbraco.BusinessLogic.Actions.IActionHandler.ReturnActions()
        {
            // return the actions for which this action handler is used
            return new IAction[] { ActionToPublish.Instance, ActionPublish.Instance, ActionUpdate.Instance };
        }

        #endregion

        #region Interface Functions

        /// <summary>
        /// Execute inital ExtendedWorkFlow task and run any associated commands
        /// </summary>
        /// <param name="Document">Document executing action</param>
        /// <param name="Action">Action taking place from return actions</param>
        /// <returns>Bool indicating if successful</returns>
        Boolean umbraco.BusinessLogic.Actions.IActionHandler.Execute(Document Document, IAction Action)
        {
            if (Action == ActionToPublish.Instance)
            {
                // Progress and workflow that currently exists
                WorkFlow[] arrWorkFlow = WorkFlow.GetWorkFlows(Document.Id);
                foreach (WorkFlow objWorkFlow in arrWorkFlow)
                {
                    // Workflow has state to handle to publish
                    if (objWorkFlow.Group.ToPublishState != null)
                        objWorkFlow.NextState(objWorkFlow.Group.ToPublishState, false);
                }

                // If no workflow is currently running start new if available
                if (arrWorkFlow.Length == 0)
                {
                    // Root path for WorkFlow
                    Node objNode = Functions.GetNodeFromPath("/WorkFlow");

                    // Check the ExtendedWorkFlow group exists
                    if (objNode.Id != 0 && objNode.NodeTypeAlias == WorkFlow.WORKFLOW_TYPE_GROUPS)
                    {
                        // Loop though all ExtendedWorkFlow to find if any match the document type
                        foreach (Node objGroup in objNode.Children)
                            if (objGroup.NodeTypeAlias == WorkFlow.WORKFLOW_TYPE_GROUP)
                                if (ContainsDocumentType(Document, objGroup))
                                {
                                    // Fire event to start the new work flow process
                                    WorkFlow objWorkFlow = WorkFlow.MakeNew(Document, objGroup);
                                }
                    }
                }

                // ExtendedWorkFlow processed
                return true;
            }
            else if (Action == ActionUpdate.Instance)
            {
                // Progress and workflow that currently exists
                WorkFlow[] arrWorkFlow = WorkFlow.GetWorkFlows(Document.Id);
                foreach (WorkFlow objWorkFlow in arrWorkFlow)
                {
                    // Workflow has state to handle to publish
                    if (objWorkFlow.Group.SaveState != null)
                        objWorkFlow.NextState(objWorkFlow.Group.SaveState, false);
                }
            }
            else if (Action == ActionPublish.Instance)
            {
                // Finish any current ExtendedWorkFlow
                WorkFlow.CompleteWorkFlow(Document);
                return true;
            }

            return true;
        }

        #endregion

        #region Private Functions

        /// <summary>
        /// Find if a documenttype exists within a documents ancestor documenttypes
        /// </summary>
        /// <param name="Document">Document to check</param>
        /// <param name="ExtendedWorkFlow">Node containing the group</param>
        /// <returns>Bool if documenttype exists</returns>
        bool ContainsDocumentType(Document Document, Node Group)
        {
            DocumentType objDocumentType = new DocumentType(Document.ContentType.Id);

            if (Group.GetProperty("documentTypes") != null)
            {
                string strExtendedWorkFlowDocumentIds = Group.GetProperty("documentTypes").Value;

                // Loop though all document types to get the parent
                do
                {
                    if (strExtendedWorkFlowDocumentIds.Contains(objDocumentType.Id.ToString()))
                        return true;

                    // Exit loop if content documents exhausted
                    if (objDocumentType.MasterContentType == 0) break;

                    // Next ancestor
                    objDocumentType = new DocumentType(objDocumentType.MasterContentType);

                } while (true);
            }

            return false;
        }

        #endregion

    }

}
